package com.xiyoukt.springboot.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.xiyoukt.springboot.util.PasswdEncode;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@MapperScan(basePackages = {"com.xiyoukt.springboot.mapper.master"}, sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterConfig {

    @Value("${spring.datasource.master.password}")
    private String password;
    @Value("${spring.datasource.master.SpareConnectionProperties}")
    private String SpareConnectionProperties;

    // 通过这个注解，标记其为主数据源
    // 本来的作用是，标志这个Bean在有多个同类Bean时，作为首选
    @Primary
    @Bean(name = "masterDataSource")
//    @ConfigurationProperties("spring.datasource.master")
    public DataSource masterDataSource(Environment env){
//        DruidDataSource druidDataSource = DataSourceBuilder.create().type(DruidDataSource.class).build();
//        druidDataSource.setPasswordCallback(dbPasswordCallback());
//        druidDataSource.setConnectionProperties(SpareConnectionProperties + ";password=" + password);
//        return druidDataSource;
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
        atomikosDataSourceBean.setUniqueResourceName("master");
        atomikosDataSourceBean.setXaProperties(build(env, "spring.datasource.master."));
        return atomikosDataSourceBean;
    }

    private Properties build(Environment env, String prefix) {
        Properties prop = new Properties();
        prop.put("name", env.getProperty(prefix + "name"));
        prop.put("url", env.getProperty(prefix + "url"));
        prop.put("username", env.getProperty(prefix + "username"));
        String password = env.getProperty(prefix + "password");
        String decodePassword = PasswdEncode.aesDecode(password, PasswdEncode.PASSWORD_KEY);
        prop.put("password", decodePassword);
        prop.put("driverClassName", env.getProperty(prefix + "driver-class-name"));
        prop.put("initialSize", env.getProperty(prefix + "initialSize", Integer.class));
        prop.put("maxActive", env.getProperty(prefix + "maxActive", Integer.class));
        prop.put("minIdle", env.getProperty(prefix + "minIdle", Integer.class));
        prop.put("maxWait", env.getProperty(prefix + "maxWait", Integer.class));
        prop.put("poolPreparedStatements", env.getProperty(prefix + "poolPreparedStatements", Boolean.class));
        prop.put("maxPoolPreparedStatementPerConnectionSize",
                env.getProperty(prefix + "maxPoolPreparedStatementPerConnectionSize", Integer.class));
        prop.put("validationQuery", env.getProperty(prefix + "validationQuery"));
        prop.put("testOnBorrow", env.getProperty(prefix + "testOnBorrow", Boolean.class));
        prop.put("testOnReturn", env.getProperty(prefix + "testOnReturn", Boolean.class));
        prop.put("testWhileIdle", env.getProperty(prefix + "testWhileIdle", Boolean.class));
        prop.put("timeBetweenEvictionRunsMillis",
                env.getProperty(prefix + "timeBetweenEvictionRunsMillis", Integer.class));
        prop.put("minEvictableIdleTimeMillis", env.getProperty(prefix + "minEvictableIdleTimeMillis", Integer.class));
        prop.put("filters", env.getProperty(prefix + "filters"));
        prop.put("useGlobalDataSourceStat", env.getProperty(prefix + "useGlobalDataSourceStat"));
        return prop;
    }

    @Bean
    public DBPasswordCallback dbPasswordCallback(){
        return new DBPasswordCallback();
    }

    @Primary
    @Bean(name = "masterSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/master/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

//    @Primary
//    @Bean(name = "masterTransactionManager")
//    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("masterDataSource") DataSource dataSource){
//        return new DataSourceTransactionManager(dataSource);
//    }

}
